package com.apestech.framework.db.session;

import com.apestech.api.tables.SequenceManage;
import com.apestech.formwork.condition.ConditionUtil;
import com.apestech.framework.db.SqlResultSet;
import com.apestech.framework.db.SqlSession;
import com.apestech.framework.db.SqlTemplate;
import com.apestech.framework.db.callback.QueryCallBackHandler;
import com.apestech.framework.db.callback.ResultValueMapping;
import com.apestech.framework.db.callback.SaveTableCallBackHandler;
import com.apestech.framework.json.JSONArray;
import com.apestech.framework.json.JSONObject;
import com.apestech.framework.sql.SqlParam;
import com.apestech.framework.util.DBUtil;
import com.apestech.framework.xml.plugin.modul.QryConfig;
import com.apestech.framework.xml.table.modul.Tables;
import java.util.ArrayList;

/**
 * @author hup
 * @create 2018-08-31-13:05
 */
public class ForUpdate extends SessionUtil{

    private SqlTemplate cn;
    private QryConfig qryConfig;
    private SqlSession session;

    public ForUpdate(SqlTemplate cn, SqlSession session){
        this.cn=cn;
        this.session=session;
    }

    public void setQryConfig(QryConfig qryConfig) {
        this.qryConfig = qryConfig;
    }

    public int update(String sql) throws Exception{
        System.out.println(sql);
        System.out.println();
        return this.cn.update(sql);
    }

    public int update_noprint(String sql) throws Exception{
        return this.cn.update(sql);
    }

    public int update(JSONObject param) throws Exception{
        SqlParam sqlparam=getQueryParam(session, param, qryConfig);
        if(sqlparam.isPrintSql()){
            System.out.println(sqlparam.getPrintSql());
        }
        if(sqlparam.getParams()!=null && sqlparam.getParams().size()>0){
            return this.cn.update(sqlparam.getExecSql(), sqlparam.getParams());
        } else {
            return this.cn.update(sqlparam.getExecSql());
        }
    }

    public void insertTable(String tabName, String sql, JSONObject param) throws Exception{
        insertTable(tabName, sql, param, null);
    }

    public void insertTable(String tabName, String sql, JSONObject param, ResultValueMapping resultValueMapping) throws Exception{
        session.getForResultSet().sql(sql, param, new QueryCallBackHandler(){
            @Override
            public void getData(SqlResultSet xxrs, com.apestech.framework.json.JSONArray rslist) throws Exception {
                SqlSession.Var var=session.getVar(xxrs);
                var.setIns("INSERT INTO "+tabName+" ("+var.getCol()+") VALUES ("+ var.getVar() +")");
                session.getForUpdate().batchUpdate(var.getIns(), xxrs, resultValueMapping);
            }
        });
    }

    public void insertTable(String stabname, String dtabname) throws Exception {
        String sql=getTwoTableInsert(stabname, dtabname, session);
        if(sql!=null){
            update(sql);
        }
    }

    public void insertTable_M(String sourcedb, String tabName, String sql, JSONObject param) throws Exception {
        insertTable_M(sourcedb, tabName, sql, param, null);
    }

    public void insertTable_M(String sourcedb, String tabName, String sql, JSONObject param, ResultValueMapping resultValueMapping) throws Exception {
        SqlSession ssession=DBUtil.getSession(sourcedb);
        ssession.getForResultSet().sql(sql, param, new QueryCallBackHandler(){
            @Override
            public void getData(SqlResultSet xxrs, com.apestech.framework.json.JSONArray rslist) throws Exception {
                SqlSession.Var var=ssession.getVar(xxrs);
                var.setIns("INSERT INTO "+tabName+" ("+var.getCol()+") VALUES ("+ var.getVar() +")");
                session.getForUpdate().batchUpdate(var.getIns(), xxrs, resultValueMapping);
            }
        });
    }

    public void insertTable_M(String sourcedb, String stabName, String dtabName) throws Exception {
        insertTable_M(sourcedb, stabName, dtabName, (ResultValueMapping)null);
    }

    public void insertTable_M(String sourcedb, String stabName, String dtabName, ResultValueMapping resultValueMapping) throws Exception {
        SqlSession ssession=DBUtil.getSession(sourcedb);
        ssession.getForResultSet().sql("SELECT * FROM "+dtabName+" WHERE 1=1 ", new QueryCallBackHandler(){
            @Override
            public void getData(SqlResultSet xxrs, com.apestech.framework.json.JSONArray rslist) throws Exception {
                SqlSession.Var var=ssession.getVar(xxrs);
                var.setIns("INSERT INTO "+stabName+" ("+var.getCol()+") VALUES ("+ var.getVar() +")");
                session.getForUpdate().batchUpdate(var.getIns(), xxrs, resultValueMapping);
            }
        });
    }

    public void insertTable_M(String sourcedb, String tabName) throws Exception {
        insertTable_M(sourcedb, tabName, (ResultValueMapping)null);
    }

    public void insertTable_M(String sourcedb, String tabName, ResultValueMapping resultValueMapping) throws Exception {
        insertTable_M(sourcedb, tabName, tabName, resultValueMapping);
    }

    public void updateTable(String sql, String tabName, final JSONObject param) throws Exception{
        updateTable(sql, tabName, param, null);
    }

    public void updateTable(String sql, String tabName, final JSONObject param, ResultValueMapping resultValueMapping) throws Exception{
        session.getForResultSet().sql(sql, param, new QueryCallBackHandler(){
            @Override
            public void getData(SqlResultSet rs, com.apestech.framework.json.JSONArray rslist) throws Exception {
                SqlSession.Var var=session.getVar(rs);
                JSONObject map=setTableSql(tabName, "update", "0", var.getCol(), true, param);
                SqlParam sqlparam=getQueryParam(session, map, qryConfig);
                String s=sqlparam.getExecSql();
                session.getForUpdate().batchUpdate(s, rs, resultValueMapping);
            }
        });
    }

    public void batchUpdate(String sql, SqlResultSet rs) throws Exception{
        batchUpdate(sql, rs, null);
    }

    public void batchUpdate(String sql, SqlResultSet rs, ResultValueMapping resultValueMapping) throws Exception{
        this.cn.batchUpdate(sql, rs, resultValueMapping);
    }

    public void batchUpdate(ArrayList<String> sqls, ArrayList<String> fields, SqlResultSet rs) throws Exception{
        this.cn.batchUpdate(sqls, fields, rs);
    }

    public int update(String sql, String fromtab, String autoCompletion, JSONObject param) throws Exception{
        param=setSql(sql, fromtab, autoCompletion, param);
        return update(param);
    }

    public int update(String sql, JSONObject param) throws Exception{
        return update(sql, null, "0", param);
    }

    public int executeTable(String tableId, JSONObject param) throws Exception{
        param=setTableId(tableId, param);
        return update(param);
    }

    private void setIdParam(String tabName, JSONObject param) throws Exception{
        Tables tab= ConditionUtil.getTables(tabName);
        if(tab!=null && tab.getSeq()!=null){
            SequenceManage sequenceManage=new SequenceManage(session);
            sequenceManage.createSeq(tab.getSeq(), true);
            String idField=tab.getSeq().getIdField();
            if(param.get(idField)==null){
                param.put(idField, sequenceManage.getNextNumByStr(tabName));
            }
        }
    }

    public int insertTable(String tabName, JSONObject param, String filter, boolean in) throws Exception{
        setIdParam(tabName, param);
        param=setTableSql(tabName, "insert", "0", filter, in, param);
        return update(param);
    }

    public int insertTable(String tabName, JSONObject param) throws Exception{
        return insertTable(tabName, param, null, true);
    }

    public int updateTable(String tabName, JSONObject param, String filter, boolean in) throws Exception{
        param=setTableSql(tabName, "update", "0", filter, in, param);
        return update(param);
    }

    public int updateTable(String tabName, JSONObject param) throws Exception{
        return updateTable(tabName, param, null, true);
    }

    public int deleteTable(String tabName, JSONObject param) throws Exception{
        param=setTableSql(tabName, "delete", "0", null, true, param);
        return update(param);
    }

    public int saveTable(String tabName, JSONObject param, String filter, boolean in, SaveTableCallBackHandler saveTableCallBackHandler) throws Exception{
        String timefield=param.getString("table_time_field");
        if(timefield==null) timefield=session.getSpecialField().getTimestamp();
        boolean time=false;
        if(param.get(timefield)!=null){
            time=session.getForResultSet().queryIsEmpty("SELECT 1 FROM "+tabName+" WHERE 1=1 ",getKeyValue(session, tabName, param));
            param.put(timefield+"_NEW","SYSDATE");
            param.put("table_time_field", timefield);
            param.put("table_time_control", "1");
        }
        setIdParam(tabName, param);
        if(saveTableCallBackHandler!=null){
            param=saveTableCallBackHandler.updateSql(param);
        }
        int r=updateTable(tabName, param, filter, in);
        if(r==0) {
            if(!time&&param.get(timefield)!=null)
                throw new Exception("当前数据记录被改变或删除，请重新查询之后再操作！");
            if(param.get(timefield)!=null){
                param.put(timefield+"_NEW","SYSDATE");
                param.put(timefield,"SYSDATE");
                param.put("table_time_field", timefield);
                param.put("table_time_control", "1");
            }
            if(saveTableCallBackHandler!=null){
                param=saveTableCallBackHandler.insertSql(param);
            }
            return insertTable(tabName, param, filter, in);
        }
        return r;
    }

    public int saveTable(String tabName, JSONObject param) throws Exception{
        return saveTable(tabName, param, null, true, null);
    }

    public int[] saveTables(String tabName, JSONArray list) throws Exception{
        return saveTables(tabName, list, null, null);
    }

    public int[] saveTables(String tabName, JSONArray list, JSONObject extend, SaveTableCallBackHandler saveTableCallBackHandler) throws Exception{
        boolean flag=false;
        int len=list.size();
        if(len==0) return new int[0];
        int[] a=new int[len];
        for(int i=0; i<len; i++){
            if(!flag && list.get(i).get("SYS_PAGE")!=null){
                i++;
                flag=true;
                continue;
            }
            JSONObject m=new JSONObject();
            if(extend!=null) m.putAll(extend);
            m.putAll(list.get(i));
            a[i]=saveTable(tabName, m, null, true,saveTableCallBackHandler);
        }
        return a;
    }

}
